import watcherQueue from "../../compiler/asyncUpdateQueue.js"
import { targetPop, targetPush } from "../dep/index.js"

let uid = 0

export default function Watcher(cb, options = {}, vm) {
    this.uid = ++uid
    this._cb = cb
    this._vm = vm
    this.value = null
    this.dirty = true // 默认为脏数据
    this.options = options
    !options.lazy && this.get() // 非计算属性直接执行
    // options.lazy && this.evaluate()
}
Watcher.prototype.run = function () {
    this.get()
}
/* 非计算属性的更新 */
Watcher.prototype.get = function () {
    // 赋值watcher 当解析模板时 会触发getter去收集当前的watcher实例
    targetPush(this)
    // 1. 执行回调函数时会有数据读取xxx.xxx    从而触发（***计算属性所依赖的数据的***）getter依赖收集
    // 2. 只有计算属性才会有返回值 将重新计算的到的结果保存到value
    this.value = this._cb.apply(this._vm)
    // 收集完依赖赋空 防止重复的的依赖收集
    targetPop()
}
/* 计算属性的更新 */
Watcher.prototype.evaluate = function () {
    // 更新计算属性值 将dirty置为干净的数据
    this.value = this.get()
    this.dirty = false // 数据更新完毕
}
// 所依赖的响应式数据更新了 计算属性值需要重新进行计算 dirty为true
Watcher.prototype.update = function () {
    // 计算属性所依赖的数据发生了变化 需要通知依赖该数据的计算属性去更新（异步更新）
    if (this.options.lazy) {
        this.dirty = true
    } else {
        watcherQueue(this)
    }
}